home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / sys / sysCalls.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  28KB  |  1,159 lines

  1. /* 
  2.  * sysCalls.c --
  3.  *
  4.  *    Miscellaneous system calls that are lumped under the Sys_ prefix.
  5.  *
  6.  * Copyright 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/sys/sysCalls.c,v 9.50 92/09/21 11:35:01 mgbaker Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14.  
  15. #include <sprite.h>
  16. #include <mach.h>
  17. #include <sys.h>
  18. #include <sysInt.h>
  19. #include <sysStats.h>
  20. #include <time.h>
  21. #include <timer.h>
  22. #include <vm.h>
  23. #include <machMon.h>
  24. #include <proc.h>
  25. #include <dbg.h>
  26. #include <fs.h>
  27. #include <fsutil.h>
  28. #include <fsprefix.h>
  29. #include <rpc.h>
  30. #include <net.h>
  31. #include <sched.h>
  32. #include <dev.h>
  33. #include <recov.h>
  34. #include <recovBox.h>
  35. #include <procMigrate.h>
  36. #include <string.h>
  37. #include <stdio.h>
  38. #include <main.h>
  39. #ifdef sun4
  40. #include <vmMach.h>
  41. #endif
  42. #ifdef sun4c
  43. #include <devSCSIC90.h>
  44. #endif /* sun4c */
  45. #include <user/sys/param.h>
  46. #include <fsrecov.h>
  47.  
  48. Boolean    sys_ErrorShutdown = FALSE;
  49. Boolean    sys_ShuttingDown = FALSE;
  50.  
  51. char    sys_HostName[MAXHOSTNAMELEN];
  52.  
  53. /*
  54.  *----------------------------------------------------------------------
  55.  *
  56.  * Sys_GetTimeOfDay --
  57.  *
  58.  *    Returns the current system time to a local user process.
  59.  *    If any argument is USER_NIL, that value is not returned.
  60.  *
  61.  *    The "real" time of day is returned, rather than the software
  62.  *    time.
  63.  *
  64.  * Results:
  65.  *    SUCCESS         The call was successful.
  66.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  67.  *
  68.  * Side effects:
  69.  *    None.
  70.  *
  71.  *----------------------------------------------------------------------
  72.  */
  73.  
  74. ReturnStatus
  75. Sys_GetTimeOfDay(timePtr, localOffsetPtr, DSTPtr)
  76.     Time    *timePtr;        /* Buffer to store the UT time. */
  77.     int        *localOffsetPtr;    /* Buffer to store the number of minutes
  78.                      * from UT (a negative value means you 
  79.                      * are west of the Prime Meridian. */
  80.     Boolean    *DSTPtr;        /* Buffer to store a flag that's TRUE
  81.                      * if DST is followed. */
  82. {
  83.     Time    curTime;
  84.     int        curLocalOffset;
  85.     Boolean    curDST;
  86.  
  87.     Timer_GetRealTimeOfDay(&curTime, &curLocalOffset, &curDST);
  88.  
  89.     if (timePtr != USER_NIL) {
  90.     if (Proc_ByteCopy(FALSE, sizeof(Time),
  91.           (Address) &curTime, (Address) timePtr) != SUCCESS) {
  92.         return(SYS_ARG_NOACCESS);
  93.     }
  94.     }
  95.     if (localOffsetPtr != USER_NIL) {
  96.     if (Proc_ByteCopy(FALSE, sizeof(int),(Address) &curLocalOffset, 
  97.                 (Address) localOffsetPtr) != SUCCESS) {
  98.         return(SYS_ARG_NOACCESS);
  99.     }
  100.     }
  101.     if (DSTPtr != USER_NIL) {
  102.     if (Proc_ByteCopy(FALSE, sizeof(Boolean),(Address) &curDST,
  103.                     (Address) DSTPtr) != SUCCESS) {
  104.         return(SYS_ARG_NOACCESS);
  105.     }
  106.     }
  107.     return(SUCCESS);
  108. }
  109.  
  110. /*
  111.  *----------------------------------------------------------------------
  112.  *
  113.  * Sys_SetTimeOfDay --
  114.  *
  115.  *    Changes the current system time to the value specified by
  116.  *    the arguments. The timePtr argument  must be valid.
  117.  *
  118.  * Results:
  119.  *    SUCCESS         The call was successful.
  120.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  121.  *
  122.  * Side effects:
  123.  *    The system time is updated to a new value.
  124.  *
  125.  *----------------------------------------------------------------------
  126.  */
  127.  
  128. ReturnStatus
  129. Sys_SetTimeOfDay(timePtr, localOffset, DST)
  130.     Time    *timePtr;    /* New value for the UT (GMT) time. */
  131.     int        localOffset;    /* new value for the offset in minutes 
  132.                  * from UT.*/
  133.     Boolean    DST;        /* If TRUE, DST is used at this site. */
  134. {
  135.     Time    newTime;
  136.  
  137.     if (timePtr == USER_NIL || 
  138.         (Proc_ByteCopy(TRUE, sizeof(Time), (Address) timePtr, 
  139.             (Address) &newTime) != SUCCESS)) {
  140.     return(SYS_ARG_NOACCESS);
  141.     }
  142.     Timer_SetTimeOfDay(newTime, localOffset, DST);
  143.     return(SUCCESS);
  144. }
  145.  
  146.  
  147. /*
  148.  *----------------------------------------------------------------------
  149.  *
  150.  * Sys_GetHostName --
  151.  *
  152.  *    Stub for the Sys_GetHostName system call.
  153.  *    Returns the name of the host.
  154.  *
  155.  * Results:
  156.  *    SUCCESS         The call was successful.
  157.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  158.  *
  159.  * Side effects:
  160.  *    None.
  161.  *
  162.  *----------------------------------------------------------------------
  163.  */
  164.  
  165. ReturnStatus
  166. Sys_GetHostName(namePtr)
  167.     char    *namePtr;        /* Buffer to store host name. */
  168. {
  169.     int        nameLen;
  170.  
  171.     nameLen = strlen(sys_HostName);
  172.     if (Proc_ByteCopy(FALSE, nameLen+1, (Address) sys_HostName, 
  173.     (Address) namePtr) != SUCCESS) {
  174.  
  175.     return SYS_ARG_NOACCESS;
  176.     }
  177.     return(SUCCESS);
  178. }
  179.  
  180. /*
  181.  *----------------------------------------------------------------------
  182.  *
  183.  * Sys_SetHostName --
  184.  *
  185.  *    Stub for the Sys_SetHostName system call.
  186.  *    Sets the name of the host. Only the root can make this call.
  187.  *
  188.  * Results:
  189.  *    SUCCESS         The call was successful.
  190.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  191.  *    SYS_INVALID_ARG        The name was too long.
  192.  *
  193.  * Side effects:
  194.  *    None.
  195.  *
  196.  *----------------------------------------------------------------------
  197.  */
  198.  
  199. ReturnStatus
  200. Sys_SetHostName(namePtr)
  201.     char    *namePtr;        /* Buffer to store host name. */
  202. {
  203.     char        tmp[MAXHOSTNAMELEN+1];
  204.     int            length;
  205.     Proc_ControlBlock     *procPtr;
  206.  
  207.     procPtr = Proc_GetEffectiveProc();
  208.     if (procPtr->effectiveUserID != 0) {
  209.     return GEN_NO_PERMISSION;
  210.     }
  211.     if (Proc_StringNCopy(MAXHOSTNAMELEN+1, namePtr, tmp, &length) != SUCCESS) {
  212.     return SYS_ARG_NOACCESS;
  213.     }
  214.     /*
  215.      * Make sure that the name wasn't too long.
  216.      */
  217.     if (length == MAXHOSTNAMELEN+1) {
  218.     return SYS_INVALID_ARG;
  219.     }
  220.     strcpy(sys_HostName, tmp);
  221.     return(SUCCESS);
  222. }
  223.  
  224. /*
  225.  *----------------------------------------------------------------------
  226.  *
  227.  * Sys_DoNothing --
  228.  *
  229.  *    This system call simply returns SUCCESS. It does not perform any
  230.  *    function.
  231.  *
  232.  * Results:
  233.  *    SUCCESS         This value is always returned.
  234.  *
  235.  * Side effects:
  236.  *    None.
  237.  *
  238.  *----------------------------------------------------------------------
  239.  */
  240.  
  241. ReturnStatus
  242. Sys_DoNothing()
  243. {
  244.     Sched_ContextSwitch(PROC_READY);
  245.     return(SUCCESS);
  246. }
  247.  
  248.  
  249. #define    MAX_WAIT_INTERVALS    3
  250. Boolean    shutdownDebug = FALSE;
  251.  
  252. /*
  253.  *----------------------------------------------------------------------
  254.  *
  255.  * Sys_Shutdown --
  256.  *
  257.  *    This system call calls appropriate routines to shutdown
  258.  *    the system in an orderly fashion.
  259.  *
  260.  * Results:
  261.  *    SUCCESS     This value is always returned.
  262.  *    SYS_ARG_NOACESS    The reboot string was inaccessible.    
  263.  *
  264.  * Side effects:
  265.  *    None.
  266.  *
  267.  *----------------------------------------------------------------------
  268.  */
  269.  
  270. ReturnStatus
  271. Sys_Shutdown(flags, rebootString)
  272.     int        flags;
  273.     char    *rebootString;
  274. {
  275.     Time        waitTime;
  276.     int            alive;
  277.     int            timesWaited;
  278.     Boolean        userDead = FALSE;
  279.     char        string[100];
  280.     int            accLength;
  281.     int            strLength;
  282.     ReturnStatus    status;
  283.     Proc_ControlBlock    *procPtr;
  284.  
  285.  
  286.     if (flags & SYS_REBOOT) {
  287.     if (rebootString == (char *) USER_NIL) {
  288.         string[0] = '\0';
  289.     } else {
  290.         status = Proc_MakeStringAccessible(100, &rebootString, &accLength,
  291.                             &strLength);
  292.         if (status != SUCCESS) {
  293.         return(SYS_ARG_NOACCESS);
  294.         }
  295.         (void) strcpy(string, rebootString);
  296.         Proc_MakeUnaccessible(rebootString, accLength);
  297.     }
  298.     }
  299.  
  300.     if (flags & SYS_DEBUG) {
  301.     sys_ErrorShutdown = TRUE;
  302.     }
  303.  
  304.     if (flags & SYS_KILL_PROCESSES) {
  305.     if (flags & SYS_WRITE_BACK) { 
  306.         /*
  307.          * Do a few initial syncs.
  308.          * These are necessary because the cache isn't getting written
  309.          * out properly with the new block cleaner.
  310.          */
  311.         printf("Doing initial syncs\n");
  312.         Fsutil_Sync(-1, 0);
  313.         Fsutil_Sync(-1, 0);
  314.         Fsutil_Sync(-1, 0);
  315.         printf("Done initial syncs\n");
  316.     }
  317.     /*
  318.      * Turn ourselves into a kernel process since we no longer need
  319.      * user process resources.
  320.      */
  321.     procPtr = Proc_GetCurrentProc();
  322.     Proc_Lock(procPtr);
  323. #ifdef sun4
  324.     /*
  325.      * Flush the virt addresses cache on the sun4 before turning ourselves
  326.      * into a kernel process. If we don't do this we will get cache
  327.      * write-back errors from dirty cache blocks of the shutdown program.
  328.      */
  329.     Mach_FlushWindowsToStack();
  330.     VmMach_FlushCurrentContext();
  331. #endif
  332.     procPtr->genFlags &= ~PROC_USER;
  333.     procPtr->genFlags |= PROC_KERNEL;
  334.     Proc_Unlock(procPtr);
  335.     VmMach_ReinitContext(procPtr);
  336.  
  337.     /*
  338.      * Get rid of any migrated processes.
  339.      */
  340.     (void) Proc_EvictForeignProcs();
  341.     
  342.     waitTime.seconds = 5;
  343.     waitTime.microseconds = 0;
  344.     while (TRUE) {
  345.         if (userDead) {
  346.         sys_ShuttingDown = TRUE;
  347.         }
  348.         timesWaited = 0;
  349.         while (TRUE) {
  350.         alive = Proc_KillAllProcesses(!userDead);
  351.         if (alive == 0) {
  352.             break;
  353.         }
  354.         if (timesWaited >= MAX_WAIT_INTERVALS) {
  355.             printf("%d %s processes still alive.\n", alive,
  356.                 userDead ? "kernel" : "user");
  357.             break;
  358.         }
  359.         timesWaited++;
  360.         printf("Waiting with %d %s processes still alive\n", alive,
  361.                 userDead ? "kernel" : "user");
  362.         if (shutdownDebug) {
  363.             DBG_CALL;
  364.         }
  365.         (void) Sync_WaitTime(waitTime);
  366.         }
  367.         if (userDead) {
  368.         break;
  369.         }
  370.         userDead = TRUE;
  371.     }
  372.     /*
  373.      * Give this process highest priority so that no other process 
  374.      * can interrupt it.
  375.      */
  376.     (void) Proc_SetPriority(PROC_MY_PID, PROC_NO_INTR_PRIORITY, FALSE);
  377.     }
  378.  
  379.     /*
  380.      * Sync the disks.
  381.      */
  382.     if (flags & SYS_WRITE_BACK) {
  383.     printf("Syncing disks\n");
  384.     Fsutil_Sync(-1, flags & SYS_KILL_PROCESSES);
  385.     }
  386.  
  387.     if (flags & SYS_HALT) {
  388.     Mach_MonAbort();
  389.     } else if (flags & SYS_REBOOT) {
  390.     Mach_MonReboot(string);
  391.     } else if (flags & SYS_DEBUG) {
  392.     sys_ShuttingDown = FALSE;
  393.     sys_ErrorShutdown = FALSE;
  394.     DBG_CALL;
  395.     }
  396.  
  397.     return(SUCCESS);
  398. }
  399.  
  400. Boolean    sys_ShouldSyncDisks = TRUE;
  401.  
  402. /*
  403.  *----------------------------------------------------------------------
  404.  *
  405.  * Sys_SyncDisks --
  406.  *
  407.  *    This routine is called when the system encountered an error and
  408.  *    the disks should be synced.
  409.  *
  410.  * Results:
  411.  *    None.
  412.  *
  413.  * Side effects:
  414.  *    None.
  415.  *
  416.  *----------------------------------------------------------------------
  417.  */
  418.  
  419. /*
  420.  * Exported so we can deny RPC requests as we die.
  421.  * Otherwise we can hang RPCs if we hang trying to sync our disks.
  422.  */
  423. Boolean    sys_ErrorSync = FALSE;
  424.  
  425.  
  426. void
  427. Sys_SyncDisks(trapType)
  428.     int    trapType;
  429. {
  430.     char    *SpriteVersion();
  431.     
  432.     if (sys_ErrorSync) {
  433.     printf("Error type %d while syncing disks.\n", trapType);
  434.     sys_ShouldSyncDisks = FALSE;
  435.     sys_ErrorSync = FALSE;
  436.     DBG_CALL;
  437.     return;
  438.     }
  439.     if (sys_ShouldSyncDisks && !mach_AtInterruptLevel && !sys_ShuttingDown &&
  440.         !dbg_BeingDebugged && (trapType != MACH_BRKPT_TRAP || sysPanicing)) {
  441.     printf("Syncing disks.  Version: %s\n", SpriteVersion());
  442.     sys_ErrorSync = TRUE;
  443.     Fsutil_Sync(-1, TRUE);
  444.     sys_ErrorSync = FALSE;
  445.     }
  446. }
  447.  
  448.  
  449. /*
  450.  *----------------------------------------------------------------------
  451.  *
  452.  * Sys_GetMachineInfo --
  453.  *
  454.  *    Returns the machine architecture and type information.
  455.  *
  456.  * Results:
  457.  *    SUCCESS         The call was successful.
  458.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  459.  *
  460.  * Side effects:
  461.  *    None.
  462.  *
  463.  *----------------------------------------------------------------------
  464.  */
  465.  
  466. ReturnStatus
  467. Sys_GetMachineInfo(archPtr, typePtr, clientIDPtr)
  468.     int    *archPtr;    /* Buffer to hold machine architecture #. */
  469.     int    *typePtr;    /* Buffer to hold machine type. */
  470.     int    *clientIDPtr;    /* Buffer to hold client ID. */
  471. {
  472.  
  473.     if (archPtr != (int *) USER_NIL) {
  474.     int arch = Mach_GetMachineArch();
  475.  
  476.     if (Proc_ByteCopy(FALSE, sizeof(int), (Address) &arch, 
  477.                 (Address) archPtr) != SUCCESS) {
  478.         return(SYS_ARG_NOACCESS);
  479.     }
  480.     }
  481.  
  482.     if (typePtr != (int *) USER_NIL) {
  483.  
  484.     int type = Mach_GetMachineType();
  485.  
  486.     if (Proc_ByteCopy(FALSE, sizeof(int), (Address) &type, 
  487.                 (Address) typePtr) != SUCCESS) {
  488.         return(SYS_ARG_NOACCESS);
  489.     }
  490.     }
  491.  
  492.  
  493.     if (clientIDPtr != (int *) USER_NIL) {
  494.     if (Proc_ByteCopy(FALSE, sizeof(int), (Address) &rpc_SpriteID, 
  495.                 (Address) clientIDPtr) != SUCCESS) {
  496.         return(SYS_ARG_NOACCESS);
  497.     }
  498.     }
  499.  
  500.     return(SUCCESS);
  501. }
  502. /*
  503.  *----------------------------------------------------------------------
  504.  *
  505.  * Sys_GetMachineInfoNew --
  506.  *
  507.  *    Returns the machine information..
  508.  *
  509.  * Results:
  510.  *    SUCCESS         The call was successful.
  511.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  512.  *
  513.  * Side effects:
  514.  *    None.
  515.  *
  516.  *----------------------------------------------------------------------
  517.  */
  518.  
  519. ReturnStatus
  520. Sys_GetMachineInfoNew(infoSize, infoBufPtr)
  521.     int            infoSize;    /* Size of the info structure. */
  522.     Address         infoBufPtr;    /* Info structure to fill in */
  523. {
  524.     Sys_MachineInfo    info;
  525.     int            bytesToCopy;
  526.  
  527.     if (infoSize < sizeof(Sys_MachineInfo)) {
  528.     bytesToCopy = infoSize;
  529.     } else {
  530.     bytesToCopy = sizeof(Sys_MachineInfo);
  531.     }
  532.     info.architecture = Mach_GetMachineArch();
  533.     info.type = Mach_GetMachineType();
  534.     info.processors = Mach_GetNumProcessors();
  535.     if (Vm_CopyOut(bytesToCopy, (Address) &info, infoBufPtr) != SUCCESS) {
  536.     return(SYS_ARG_NOACCESS);
  537.     }
  538.     return(SUCCESS);
  539. }
  540.  
  541.  
  542. /*
  543.  *----------------------------------------------------------------------
  544.  *
  545.  * Sys_StatsStub --
  546.  *
  547.  *    System call stub for the Statistics hook.
  548.  *
  549.  * Results:
  550.  *    SUCCESS            - the data were returned.
  551.  *    GEN_INVALID_ARG        - if a bad argument was passed in.
  552.  *    ?            - result from Vm_CopyOut.
  553.  *    
  554.  *
  555.  * Side effects:
  556.  *    Fill in the requested statistics.
  557.  *
  558.  *----------------------------------------------------------------------
  559.  */
  560. ReturnStatus
  561. Sys_StatsStub(command, option, argPtr)
  562.     int command;        /* Specifies what to do */
  563.     int option;            /* Modifier for command */
  564.     Address argPtr;        /* Argument for command */
  565. {
  566.     /*
  567.      * These extern decl's are temporary and should be removed when the
  568.      * START_STATS and END_STATS are removed.
  569.      */
  570.     extern void    Dev_StartIOStats();
  571.     extern void    Dev_StopIOStats();
  572.     extern void    Sched_StopSchedStats();
  573.     extern void    Sched_StartSchedStats();
  574.  
  575.     ReturnStatus status = SUCCESS;
  576.     
  577.     switch(command) {
  578.     case SYS_GET_VERSION_STRING: {
  579.         /*
  580.          * option is the length of the storage referenced by argPtr.
  581.          */
  582.         register int length;
  583.         register char *version;
  584.         version = (char *)SpriteVersion();
  585.         length = strlen(version) + 1;
  586.         if (option <= 0) {
  587.         status = GEN_INVALID_ARG;
  588.         break;
  589.         }
  590.         if (option < length) {
  591.         length = option;
  592.         }
  593.         status = Vm_CopyOut(length, version, argPtr);
  594.         break;
  595.     }
  596.     case SYS_SYNC_STATS: {
  597.         register Sync_Instrument *syncStatPtr;
  598.  
  599.         syncStatPtr = (Sync_Instrument *)argPtr;
  600.         if (syncStatPtr == (Sync_Instrument *)NIL ||
  601.         syncStatPtr == (Sync_Instrument *)0 ||
  602.         syncStatPtr == (Sync_Instrument *)USER_NIL) {
  603.         
  604.         Sync_PrintStat();
  605.         } else if (option <= 0) {
  606.         status = GEN_INVALID_ARG;
  607.         break;
  608.         } else {
  609.         if (option > sizeof(sync_Instrument)) {
  610.             option = sizeof(sync_Instrument);
  611.         }
  612.         status = Vm_CopyOut(option,
  613.                   (Address) sync_Instrument,
  614.                   (Address) syncStatPtr);
  615.         }
  616.         break;
  617.     }
  618.     case SYS_VM_STATS: {
  619.         if (argPtr == (Address)NIL ||
  620.         argPtr == (Address)0 ||
  621.         argPtr == (Address)USER_NIL) {
  622.         return(GEN_INVALID_ARG);
  623.         } else {
  624.         status = Vm_CopyOut(sizeof(Vm_Stat), (Address)&vmStat, argPtr);
  625.         }
  626.         break;
  627.     }
  628.     case SYS_SCHED_STATS: {
  629.         Sched_Instrument *schedStatPtr;
  630.         Time curTime;
  631.  
  632.         schedStatPtr = (Sched_Instrument *)argPtr;
  633.         if (schedStatPtr == (Sched_Instrument *)NIL ||
  634.         schedStatPtr == (Sched_Instrument *)0 ||
  635.         schedStatPtr == (Sched_Instrument *)USER_NIL) {
  636.         
  637.         Sched_PrintStat();
  638.         } else {
  639.         register int cpu;
  640.         for (cpu = 0; cpu < MACH_MAX_NUM_PROCESSORS; cpu++) {  
  641.             Timer_TicksToTime(sched_Instrument.processor[cpu].
  642.                         noProcessRunning,
  643.                   &sched_Instrument.processor[cpu].idleTime);
  644.         }
  645.         /*
  646.          * If no interrupts received, dev_LastConsoleInput will
  647.          * be 0, so set it to the current time.  This will happen
  648.          * the first time Sched_Stats is called if there were no
  649.          * keyboard interrupts already.
  650.          *
  651.          * Note: dev_LastConsoleInput can't be set during
  652.          * initialization because the timer has not yet been
  653.          * initialized.
  654.          */
  655.         if (dev_LastConsoleInput.seconds == 0) {
  656.             Timer_GetTimeOfDay(&dev_LastConsoleInput,
  657.                        (int *) NIL, (Boolean *) NIL);
  658.         }
  659.         Timer_GetTimeOfDay(&curTime, (int *) NIL, (Boolean *) NIL);
  660.         Time_Subtract(curTime, dev_LastConsoleInput,
  661.                   &sched_Instrument.noUserInput);
  662.         status = Vm_CopyOut(sizeof(Sched_Instrument),
  663.                       (Address)&sched_Instrument, argPtr);
  664.         }
  665.         break;
  666.     }
  667.     case SYS_RPC_CLT_STATS:
  668.     case SYS_RPC_SRV_STATS:
  669.     case SYS_RPC_TRACE_STATS:
  670.     case SYS_RPC_SERVER_HIST:
  671.     case SYS_RPC_CLIENT_HIST:
  672.     case SYS_RPC_SRV_STATE:
  673.     case SYS_RPC_CLT_STATE:
  674.     case SYS_RPC_ENABLE_SERVICE:
  675.     case SYS_RPC_SRV_COUNTS:
  676.     case SYS_RPC_CALL_COUNTS:
  677.     case SYS_RPC_SET_MAX:
  678.     case SYS_RPC_SET_NUM:
  679.     case SYS_RPC_NEG_ACKS:
  680.     case SYS_RPC_CHANNEL_NEG_ACKS:
  681.     case SYS_RPC_NUM_NACK_BUFS:
  682.     case SYS_RPC_SANITY_CHECK:
  683.         status = Rpc_GetStats(command, option, argPtr);
  684.         break;
  685.     case SYS_PROC_MIGRATION: {
  686.         switch(option) {
  687.         /*
  688.          * The first two are for backward compatibility.
  689.          */
  690.         case SYS_PROC_MIG_ALLOW: 
  691.         case SYS_PROC_MIG_REFUSE: {
  692.             register Proc_ControlBlock *procPtr;
  693.             procPtr = Proc_GetEffectiveProc();
  694.             if (procPtr->effectiveUserID != 0) {
  695.             status = GEN_NO_PERMISSION;
  696.             } else {
  697.             /*
  698.              * This part is simplified for now.
  699.              */
  700.             if (option == SYS_PROC_MIG_REFUSE) {
  701.                 proc_AllowMigrationState &= ~PROC_MIG_IMPORT_ALL;
  702.             } else {
  703.                 proc_AllowMigrationState |= PROC_MIG_IMPORT_ALL;
  704.             }
  705.             }
  706.         }
  707.         break;
  708.  
  709.         case SYS_PROC_MIG_SET_STATE: {
  710.             register Proc_ControlBlock *procPtr;
  711.             int arg;
  712.  
  713.             procPtr = Proc_GetEffectiveProc();
  714.             if (procPtr->effectiveUserID != 0) {
  715.             status = GEN_NO_PERMISSION;
  716.             } else {
  717.             status = Vm_CopyIn(sizeof(int), argPtr, (Address)&arg);
  718.             if (status == SUCCESS) {
  719.                 proc_AllowMigrationState = arg;
  720.             }
  721.             }
  722.         }
  723.         break;
  724.  
  725.         /*
  726.          * Also obsolete, here for backward compatibility for a while.
  727.          */
  728.             case SYS_PROC_MIG_GET_STATUS: {
  729.             if (argPtr != (Address) NIL) {
  730.             /*
  731.              * This part is simplified for now.
  732.              */
  733.             int refuse;
  734.             if (proc_AllowMigrationState & PROC_MIG_IMPORT_ALL) {
  735.                 refuse = 0;
  736.             } else {
  737.                 refuse = 1;
  738.             }
  739.             status = Vm_CopyOut(sizeof(Boolean),
  740.                         (Address)&refuse,
  741.                         argPtr);
  742.             } else {
  743.             status = GEN_INVALID_ARG;
  744.             }
  745.         }
  746.         break;
  747.             case SYS_PROC_MIG_GET_STATE: {
  748.             if (argPtr != (Address) NIL) {
  749.             status = Vm_CopyOut(sizeof(Boolean),
  750.                         (Address)&proc_AllowMigrationState,
  751.                         argPtr);
  752.             } else {
  753.             status = GEN_INVALID_ARG;
  754.             }
  755.         }
  756.         break;
  757.             case SYS_PROC_MIG_GET_VERSION: {
  758.             if (argPtr != (Address) NIL) {
  759.             status = Vm_CopyOut(sizeof(int),
  760.                         (Address)&proc_MigrationVersion,
  761.                         argPtr);
  762.             } else {
  763.             status = GEN_INVALID_ARG;
  764.             }
  765.         }
  766.         break;
  767.             case SYS_PROC_MIG_SET_VERSION: {
  768.             register Proc_ControlBlock *procPtr;
  769.             int arg;
  770.  
  771.             procPtr = Proc_GetEffectiveProc();
  772.             if (procPtr->effectiveUserID != 0) {
  773.             status = GEN_NO_PERMISSION;
  774.             } else {
  775.             status = Vm_CopyIn(sizeof(int), argPtr, (Address)&arg);
  776.             if (status == SUCCESS && arg >= 0) {
  777.                 proc_MigrationVersion = arg;
  778.             } else if (status == SUCCESS) {
  779.                 status = GEN_INVALID_ARG;
  780.             }
  781.             }
  782.         }
  783.         break;
  784.         case SYS_PROC_MIG_SET_DEBUG: {
  785.             int arg;
  786.             status = Vm_CopyIn(sizeof(int), argPtr, (Address)&arg);
  787.             if (status == SUCCESS && arg >= 0) {
  788.             proc_MigDebugLevel = arg;
  789.             } else if (status == SUCCESS) {
  790.             status = GEN_INVALID_ARG;
  791.             }
  792.         }
  793.         break;
  794.  
  795.         case SYS_PROC_MIG_GET_STATS: {
  796.             status = Proc_MigGetStats(argPtr);
  797.             break;
  798.         }
  799.         case SYS_PROC_MIG_RESET_STATS: {
  800.             status = Proc_MigResetStats();
  801.             break;
  802.         }
  803.         default:{
  804.             status = GEN_INVALID_ARG;
  805.         }
  806.         break;
  807.         }
  808.         break;
  809.     }
  810.     
  811.     case SYS_PROC_TRACE_STATS: {
  812.         switch(option) {
  813.         case SYS_PROC_TRACING_PRINT:
  814.             printf("%s %s\n", "Warning:",
  815.                 "Printing of proc trace records not implemented.");
  816.             break;
  817.         case SYS_PROC_TRACING_ON:
  818.             Proc_MigrateStartTracing();
  819.             break;
  820.         case SYS_PROC_TRACING_OFF:
  821.             proc_DoTrace = FALSE;
  822.             break;
  823.         default:
  824.             /*
  825.              * The default is to copy 'option' trace records.
  826.              */
  827.             status = Trace_Dump(proc_TraceHdrPtr, option, argPtr);
  828.             break;
  829.         }
  830.         break;
  831.     }
  832.     case SYS_FS_PREFIX_STATS: {
  833.         status = Fsprefix_Dump(option, argPtr);
  834.         break;
  835.     }
  836.     case SYS_FS_PREFIX_EXPORT: {
  837.         status = Fsprefix_DumpExport(option, argPtr);
  838.         break;
  839.     }
  840.     case SYS_SYS_CALL_STATS_ENABLE: {
  841.         printf ("%s system call profiling; was %s.\n",
  842.             option ? "Enabling" : "Disabling",
  843.             sys_CallProfiling ? "enabled" : "disabled");
  844.         sys_CallProfiling = option;
  845.         break;
  846.     }
  847.     case SYS_SYS_CALL_TIMES: {
  848.         status = Sys_OutputNumCalls(option, argPtr, TRUE);
  849.         break;
  850.     }
  851.     case SYS_SYS_CALL_STATS: {
  852.         status = Sys_OutputNumCalls(option, argPtr, FALSE);
  853.         break;
  854.     }
  855.     case SYS_NET_GET_ROUTE: {
  856.         status = Net_IDToRouteOldStub(option, 
  857.                 sizeof(Net_RouteInfoOld), argPtr);
  858.         break;
  859.     }
  860.     case SYS_NET_ETHER_STATS: {
  861.         Net_Stats    stats;
  862.         status = Net_GetStats(NET_NETWORK_ETHER, &stats);
  863.         status = Vm_CopyOut(sizeof(Net_EtherStats),
  864.                 (Address)&stats.ether, (Address)argPtr);
  865.         break;
  866.     }
  867.     case SYS_DISK_STATS: {
  868.         int            count;
  869.         Sys_DiskStats    *statArrPtr;
  870.  
  871.         if ((option < 0) || (option > 10000)) {
  872.         status = GEN_INVALID_ARG;
  873.         } else { 
  874.         statArrPtr = (Sys_DiskStats *)
  875.                     malloc(sizeof(Sys_DiskStats) * option);
  876.         count = Dev_GetDiskStats(statArrPtr, option);
  877.         status = Vm_CopyOut(sizeof(Sys_DiskStats) * count, 
  878.                     (Address)statArrPtr, (Address)argPtr);
  879.         free((Address) statArrPtr);
  880.         }
  881.         break;
  882.     }
  883.     case SYS_LOCK_STATS: {
  884.         status = Sync_GetLockStats(option, argPtr);
  885.         break;
  886.     }
  887.     case SYS_LOCK_RESET_STATS: {
  888.         status = Sync_ResetLockStats();
  889.         break;
  890.     }
  891.     case SYS_INST_COUNTS: {
  892. #ifdef spur
  893.         Mach_InstCountInfo    info[MACH_MAX_INST_COUNT];
  894.         Mach_GetInstCountInfo(info);
  895.         Vm_CopyOut(sizeof(info), (Address) info, 
  896.         argPtr);
  897.         status = SUCCESS;
  898. #else
  899.         status = GEN_NOT_IMPLEMENTED;
  900. #endif
  901.         break;
  902.     }
  903.     case SYS_RESET_INST_COUNTS: {
  904. #ifdef spur
  905.         bzero(mach_InstCount, sizeof(mach_InstCount));
  906.         status = SUCCESS;
  907. #else
  908.         status = GEN_NOT_IMPLEMENTED;
  909. #endif
  910.         break;
  911.     }
  912.     case SYS_RECOV_STATS: {
  913.         status = Recov_GetStats(option, argPtr);
  914.         break;
  915.     }
  916.     case SYS_RECOV_PRINT: {
  917.         Recov_ChangePrintLevel(option);
  918.         status = SUCCESS;
  919.         break;
  920.     }
  921.     case SYS_RECOV_ABS_PINGS: {
  922.         recov_AbsoluteIntervals = option;
  923.         status = SUCCESS;
  924.         break;
  925.     }
  926.     case SYS_FS_RECOV_INFO: {
  927.         int        length;
  928.         Address    resultPtr;
  929.         int        lengthNeeded;
  930.  
  931.         resultPtr = argPtr;
  932.         /* option is actually an in/out param */
  933.         status = Vm_CopyIn(sizeof (int), (Address) option,
  934.             (Address) &length);
  935.         if (status != SUCCESS) {
  936.         break;
  937.         }
  938.         if (length != 0 && (resultPtr == (Address) NIL || resultPtr ==
  939.             (Address) 0 || resultPtr == (Address) USER_NIL)) {
  940.         status = GEN_INVALID_ARG;
  941.         break;
  942.         }
  943.         if (length > 0) {
  944.         resultPtr = (Address) malloc(length);
  945.         } else {
  946.         resultPtr = (Address) NIL;
  947.         }
  948.         status = Fsutil_FsRecovInfo(length,
  949.             (Fsutil_FsRecovNamedStats *) resultPtr, &lengthNeeded);
  950.         if (status != SUCCESS) {
  951.         if (resultPtr != (Address) NIL) {
  952.             free(resultPtr);
  953.         }
  954.         break;
  955.         }
  956.         status = Vm_CopyOut(length, resultPtr, argPtr);
  957.         if (status != SUCCESS) {
  958.         if (resultPtr != (Address) NIL) {
  959.             free(resultPtr);
  960.         }
  961.         break;
  962.         }
  963.         status = Vm_CopyOut(sizeof (int), (Address) &lengthNeeded,
  964.             (Address) option);
  965.         if (resultPtr != (Address) NIL) {
  966.         free(resultPtr);
  967.         }
  968.         break;
  969.     }
  970.     case SYS_RECOV_CLIENT_INFO: {
  971.         int        length;
  972.         Address    resultPtr;
  973.         int        lengthNeeded;
  974.  
  975.         resultPtr = argPtr;
  976.         /* option is actually an in/out param */
  977.         status = Vm_CopyIn(sizeof (int), (Address) option,
  978.             (Address) &length);
  979.         if (status != SUCCESS) {
  980.         break;
  981.         }
  982.         if (length != 0 && (resultPtr == (Address) NIL || resultPtr ==
  983.             (Address) 0 || resultPtr == (Address) USER_NIL)) {
  984.         status = GEN_INVALID_ARG;
  985.         break;
  986.         }
  987.         if (length > 0) {
  988.         resultPtr = (Address) malloc(length);
  989.         } else {
  990.         resultPtr = (Address) NIL;
  991.         }
  992.         status = Recov_DumpClientRecovInfo(length, resultPtr,
  993.             &lengthNeeded);
  994.         if (status != SUCCESS) {
  995.         if (resultPtr != (Address) NIL) {
  996.             free(resultPtr);
  997.         }
  998.         break;
  999.         }
  1000.         status = Vm_CopyOut(length, resultPtr, argPtr);
  1001.         if (status != SUCCESS) {
  1002.         if (resultPtr != (Address) NIL) {
  1003.             free(resultPtr);
  1004.         }
  1005.         break;
  1006.         }
  1007.         status = Vm_CopyOut(sizeof (int), (Address) &lengthNeeded,
  1008.             (Address) option);
  1009.         if (resultPtr != (Address) NIL) {
  1010.         free(resultPtr);
  1011.         }
  1012.         break;
  1013.     }
  1014.     case SYS_RPC_SERVER_TRACE:
  1015.         if (option == TRUE) {
  1016.         Rpc_OkayToTrace(TRUE);
  1017.         } else  {
  1018.         Rpc_OkayToTrace(FALSE);
  1019.         }
  1020.         status = SUCCESS;
  1021.         
  1022.         break;
  1023.     case SYS_RPC_SERVER_FREE:
  1024.         Rpc_FreeTraces();
  1025.         status = SUCCESS;
  1026.  
  1027.         break;
  1028.     case SYS_RPC_SERVER_INFO: {
  1029.         int        length;
  1030.         Address    resultPtr;
  1031.         int        lengthNeeded;
  1032.  
  1033.         resultPtr = argPtr;
  1034.         /* option is actually an in/out param */
  1035.         status = Vm_CopyIn(sizeof (int), (Address) option,
  1036.             (Address) &length);
  1037.         if (status != SUCCESS) {
  1038.         break;
  1039.         }
  1040.         if (length != 0 && (resultPtr == (Address) NIL || resultPtr ==
  1041.             (Address) 0 || resultPtr == (Address) USER_NIL)) {
  1042.         status = GEN_INVALID_ARG;
  1043.         break;
  1044.         }
  1045.         if (length > 0) {
  1046.         resultPtr = (Address) malloc(length);
  1047.         } else {
  1048.         resultPtr = (Address) NIL;
  1049.         }
  1050.         status = Rpc_DumpServerTraces(length,
  1051.             (RpcServerUserStateInfo *)resultPtr, &lengthNeeded);
  1052.         if (status != SUCCESS) {
  1053.         if (resultPtr != (Address) NIL) {
  1054.             free(resultPtr);
  1055.         }
  1056.         break;
  1057.         }
  1058.         status = Vm_CopyOut(length, resultPtr, argPtr);
  1059.         if (status != SUCCESS) {
  1060.         if (resultPtr != (Address) NIL) {
  1061.             free(resultPtr);
  1062.         }
  1063.         break;
  1064.         }
  1065.         status = Vm_CopyOut(sizeof (int), (Address) &lengthNeeded,
  1066.             (Address) option);
  1067.         if (resultPtr != (Address) NIL) {
  1068.         free(resultPtr);
  1069.         }
  1070.         break;
  1071.     }
  1072.     case SYS_START_STATS: {
  1073.         /* schedule the stuff */
  1074.         Dev_StartIOStats();
  1075.         Sched_StartSchedStats();
  1076.         status = SUCCESS;
  1077.         break;
  1078.     }
  1079.     case SYS_END_STATS: {
  1080.         /* deschedule the stuff */
  1081.         Dev_StopIOStats();
  1082.         Sched_StopSchedStats();
  1083.         status = SUCCESS;
  1084.         break;
  1085.     }
  1086. #ifdef sun4c
  1087.     case SYS_FAST_RESTART: {
  1088.         if (option == -1) {
  1089.         /* Do a fast reboot -- Turn off interrupts. */
  1090.         DISABLE_INTR();
  1091.         /* restart */
  1092.         Mach_FastBoot();
  1093.         } else {
  1094.         /* Set debug level. */
  1095.         printf("Setting fsrecov_DebugLevel to %d, was %d.\n",
  1096.             option, fsrecov_DebugLevel);
  1097.         fsrecov_DebugLevel = option;
  1098.         status = SUCCESS;
  1099.         }
  1100.         break;
  1101.     }
  1102.         case SYS_DEV_CHANGE_SCSI_DEBUG: {
  1103.         Dev_ChangeScsiDebugLevel(option);
  1104.         status = SUCCESS;
  1105.         break;
  1106.     }
  1107.         case SYS_MACH_PRINT_DEV_TREE: {
  1108.         Mach_MonTraverseAndPrintDevTree();
  1109.         status = SUCCESS;
  1110.         break;
  1111.     }
  1112. #endif /* sun4c */
  1113.     case SYS_PROC_ADD_SERVERS: {
  1114.         if (option < 0) {
  1115.         status = GEN_INVALID_ARG;
  1116.         } else {
  1117.         int    numCreated;
  1118.         numCreated = Proc_ServerProcCreate(option);
  1119.         printf("Adding %d Proc_Servers to kernel\n", numCreated);
  1120.         status = SUCCESS;
  1121.         }
  1122.         break;
  1123.     }
  1124.     case SYS_RECOV_BOX: {
  1125.         switch(option) {
  1126.         case RECOV_PRINT_REBOOT_TIMES:
  1127.         case RECOV_TEST_ADD_DELETE:
  1128.         case RECOV_TEST_ADD: {
  1129.         status = Fsrecov_TestCmd(option, argPtr);
  1130.         break;
  1131.         }
  1132.         default:
  1133.         status = Recov_Cmd(option, argPtr);
  1134.         break;
  1135.         }
  1136.         break;
  1137.     }
  1138.         case SYS_DONT_PRINT: {
  1139.             if (option != 0) {
  1140.                 /* Make it so we can't print. */
  1141.                 sys_DontPrint = TRUE;
  1142.             } else {
  1143.                 sys_DontPrint = FALSE;
  1144.             }
  1145.             status = SUCCESS;
  1146.             break;
  1147.         }
  1148.     case SYS_RECOV_PARAMS: {
  1149.         status = Recov_Cmd(option, argPtr);
  1150.         break;
  1151.     }
  1152.         default:
  1153.             status = GEN_INVALID_ARG;
  1154.             break;
  1155.     }
  1156.  
  1157.     return(status);
  1158. }
  1159.